package com.beiding.jsonanalyzer.querylink;

import com.beiding.jsonanalyzer.analyze.Joiner;
import com.beiding.jsonanalyzer.flow.BranchNode;
import com.beiding.jsonanalyzer.flow.ValueNode;
import com.beiding.jsonanalyzer.visit.VisitAble;

import java.util.HashMap;
import java.util.Map;

public class UnionQueryLinkNode<W extends ValueNode> extends QueryLinkNodeAdapter<W> {

    //联合两个结果


    private QueryLinkNode<W> another;
    private boolean all;

    public UnionQueryLinkNode(QueryLinkNode<W> pre, QueryLinkNode<W> another, boolean all) {
        super(pre);
        this.another = another;
        this.all = all;
    }


    @Override
    protected VisitAble<BranchNode<W>> doExec(VisitAble<BranchNode<W>> preResult) {


        return visitor -> {
            Map<Object, BranchNode<W>> left = new HashMap<>();
            Map<Object, BranchNode<W>> right = new HashMap<>();

            //todo 改造成性能更高的锁结构
            Object newBranchLock = new Object();

            preResult.visit(b -> {
                {
                    //当左侧产生一个分支时
                    synchronized (newBranchLock) {
                        //先放入到左侧
                        left.put(b.getBranch().getRefer(), b);
                        BranchNode<W> rn = right.get(b.getBranch().getRefer());
                        if (rn == null) {
                            return;
                        }

                        BranchNode<W> queuedBranch = new BranchNode<>(b.getBranch());

                        //此处生成一个新的流
                        Joiner.union(queuedBranch, b, rn, all);

                        //创建一个新的数据流
                        visitor.onNode(queuedBranch);
                    }

                }
            });

            VisitAble<BranchNode<W>> bs = another.exec().getBranches();

            bs.visit(b -> {
                //当右侧产生一个分支时
                synchronized (newBranchLock) {
                    right.put(b.getBranch().getRefer(), b);
                    BranchNode<W> ln = left.get(b.getBranch().getRefer());
                    if (ln == null) {
                        return;
                    }

                    //创建一个新的数据流
                    BranchNode<W> queuedBranch = new BranchNode<>(b.getBranch());

                    //此处生成一个新的流
                    Joiner.union(queuedBranch, ln, b, all);

                    visitor.onNode(queuedBranch);
                }
            });
        };
    }
}
